package com.brillilab.service.logic.plans;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import com.brillilab.common.alioss.OssFileEnum;
import com.brillilab.common.utils.DateUtil;
import com.brillilab.common.utils.MyBeanUtils;
import com.brillilab.domain.enums.common.BoolEnum;
import com.brillilab.domain.enums.common.IsDeleteEnum;
import com.brillilab.domain.enums.experiment.ExperimentStateEnum;
import com.brillilab.domain.enums.lab.LabMemberEnum;
import com.brillilab.domain.enums.plans.PlanMemberRoleEnum;
import com.brillilab.domain.enums.team.TeamMemberStateEnum;
import com.brillilab.domain.enums.topic.TopicStateEnum;
import com.brillilab.domain.po.experiments.Experiment;
import com.brillilab.domain.po.plans.Plan;
import com.brillilab.domain.po.plans.PlanExperimentGroup;
import com.brillilab.domain.po.plans.PlanTargetGroup;
import com.brillilab.domain.po.team.TeamMember;
import com.brillilab.domain.po.topics.Topic;
import com.brillilab.domain.po.topics.TopicDirection;
import com.brillilab.domain.po.topics.TopicExperiment;
import com.brillilab.domain.po.topics.TopicTarget;
import com.brillilab.domain.po.user.Users;
import com.brillilab.domain.vo.experiments.ExperimentStartVo;
import com.brillilab.domain.vo.home.HomePlanCompleteVo;
import com.brillilab.domain.vo.home.HomeWeekPlanVo;
import com.brillilab.domain.vo.lab.LabMemberInfo;
import com.brillilab.domain.vo.lab.MemberInfoVo;
import com.brillilab.domain.vo.plans.PlanAddVo;
import com.brillilab.domain.vo.plans.PlanExperimentAddVo;
import com.brillilab.domain.vo.plans.PlanMemberRoleVo;
import com.brillilab.domain.vo.plans.PlanTargetAddVo;
import com.brillilab.domain.vo.plans.PlanTopicListVo;
import com.brillilab.domain.vo.plans.PlanTopicTargetListVo;
import com.brillilab.domain.vo.plans.PlanTopicVo;
import com.brillilab.domain.vo.plans.PlanVo;
import com.brillilab.domain.vo.team.TeamMemberVo;
import com.brillilab.domain.vo.topics.TopicExperimentVo;
import com.brillilab.domain.vo.topics.TopicListVo;
import com.brillilab.domain.vo.user.UserInfoVo;
import com.brillilab.service.core.experiments.IExperimentService;
import com.brillilab.service.core.lab.ILabMemberService;
import com.brillilab.service.core.plans.IPlanExperimentGroupService;
import com.brillilab.service.core.plans.IPlanService;
import com.brillilab.service.core.plans.IPlanTargetGroupService;
import com.brillilab.service.core.system.IFileManageService;
import com.brillilab.service.core.team.ITeamMemberService;
import com.brillilab.service.core.topics.ITopicDirectionService;
import com.brillilab.service.core.topics.ITopicExperimentService;
import com.brillilab.service.core.topics.ITopicMemberService;
import com.brillilab.service.core.topics.ITopicService;
import com.brillilab.service.core.topics.ITopicTargetService;
import com.brillilab.service.core.user.IUsersService;
import com.brillilab.service.logic.experiments.ExperimentLogic;
import com.brillilab.service.logic.team.TeamLogic;
import com.brillilab.service.logic.topics.TopicLogic;
import com.brillilab.service.module.message.producer.MessageProducer;
import com.brillilab.service.module.message.template.impl.plan.ManagerAddPlanTemplate;
import com.brillilab.service.module.message.template.impl.plan.ManagerModifyPlanTimeTemplate;
import com.brillilab.service.module.message.template.impl.plan.ManagerRemovePlanTemplate;
import com.brillilab.service.module.message.template.impl.plan.MemberDoExperimentTargetJoinPlanTemp;

/**
 * @author zlb
 * @Title: PlanLogic
 * @ProjectName brill_lab
 * @Description: TODO
 * @date 2019/9/5 14:47
 */
@Service
@Transactional
public class PlanLogic {

	@Resource
	private IPlanService planService;
	@Resource
	private IExperimentService experimentService;
	@Resource
	private ITopicService topicService;
	@Resource
	private ITopicTargetService topicTargetService;
	@Resource
	private ITopicDirectionService topicDirectionService;
	@Resource
	private ITopicExperimentService topicExperimentService;
	@Resource
	private IFileManageService fileManageService;
	@Resource
	private ILabMemberService labMemberService;
	@Resource
	private TeamLogic teamLogic;
	@Resource
	private ITeamMemberService teamMemberService;
	@Resource
	private ITopicMemberService topicMemberService;
	@Resource
	private IPlanTargetGroupService planTargetGroupService;
	@Resource
	private IPlanExperimentGroupService planExperimentGroupService;
	@Resource
	private TopicLogic topicLogic;
	@Resource
	private ExperimentLogic experimentLogic;
	@Resource
	private MessageProducer messageProducer;
	@Resource
	private IUsersService usersService;


	
	/** WuMenghao */
	/**
	 * 获取可切换课题列表
	 *
	 * @param labMemberId
	 * @return
	 */
	public List<PlanTopicListVo> getPlanTopicList(Long labMemberId) {
		List<Topic> topics = topicService.selectList(labMemberId,
				Arrays.asList(TopicStateEnum.NOT_STARTED.getValue(), TopicStateEnum.UNDER_WAY.getValue()));
		List<PlanTopicListVo> result = topics.stream().filter(e -> e.getIsDelete().equals(BoolEnum.FALSE.getValue()))
				.map(e -> {
					PlanTopicListVo vo = new PlanTopicListVo();
					vo.setTopicId(e.getId());
					vo.setTopicName(e.getName());
					return vo;
				}).collect(Collectors.toList());
		return result;
	}

	/**
	 * 根据课题ID获取实验流列表
	 *
	 * @param topicId
	 * @param labId
	 * @param labMemberId
	 * @return
	 */
	public PlanTopicVo getTargetListByTopicId(Long topicId, Long labId, UserInfoVo userInfo) {
		Topic topic = topicService.selectById(topicId);
		Assert.notNull(topic, "课题不存在!");
		Assert.isTrue(topic.getLabId().equals(labId), "课题不属于当前实验室!");

		List<TopicTarget> topicTargets = planTargetGroupService.selectListByTopicId(topic.getId());
		boolean isPower = topicLogic.topicEditPower(topic, userInfo);
		boolean bool = isPower || topicLogic.isTopicMember(topic.getId(), userInfo.getLabMemberId());
		List<PlanTopicTargetListVo> pttlvs = topicTargets.stream().map(e -> {
			PlanTopicTargetListVo vo = new PlanTopicTargetListVo();
			vo.setFigure(e.getFigure());
			vo.setColor(e.getColor());
			vo.setName(e.getName());
			vo.setTopicDirectionId(e.getTopicDirectionId());
			vo.setTopicId(e.getTopicId());
			vo.setTopicTargetId(e.getId());
			if (TopicStateEnum.UNDER_WAY.getValue().equals(topic.getState())) {
				int count = planService.getMeNoCompleteNum(e.getId(), userInfo.getLabMemberId());
				vo.setIsPlanNotFinish(count > 0 ? BoolEnum.TRUE.getValue() : BoolEnum.FALSE.getValue());
			}
			if (bool && !TopicStateEnum.COMPLETE.getValue().equals(topic.getState())) {
				boolean isAddPlan = planService.isAddPlan(e.getId());
				if (isAddPlan) {
					vo.setIsAddPlan(BoolEnum.TRUE.getValue());
				}
			}
			return vo;
		}).collect(Collectors.toList());

		// PlanTopicVo
		PlanTopicVo planTopicVo = new PlanTopicVo();
		planTopicVo.setState(topic.getState());
		planTopicVo.setTopicId(topic.getId());
		planTopicVo.setTopicName(topic.getName());
		planTopicVo.setMainExecutorId(topic.getExecutorId());
		planTopicVo.setTopicTargetList(pttlvs);
		return planTopicVo;
	}

	/**
	 * 获取相同方向下的实验流列表
	 *
	 * @param topicDirectionId
	 * @param labId
	 * @param labMemberId
	 * @return
	 */
	@Deprecated
	public PlanTopicVo getTargetList(Long topicDirectionId, Long labId, Long labMemberId) {
		TopicDirection topicDirection = topicDirectionService.getById(topicDirectionId);
		Assert.notNull(topicDirection, "研究内容不存在");

		Topic topic = topicService.selectById(topicDirection.getTopicId());
		Assert.notNull(topic, "课题不存在!");
		Assert.isTrue(topic.getLabId().equals(labId), "课题不属于当前实验室!");

		List<TopicTarget> targets = topicTargetService.selectListByTopicDirectionId(topicDirectionId);
		List<PlanTopicTargetListVo> pttlvs = targets.stream().map(e -> {
			PlanTopicTargetListVo vo = new PlanTopicTargetListVo();
			vo.setFigure(e.getFigure());
			vo.setColor(e.getColor());
			vo.setName(e.getName());
			vo.setTopicDirectionId(e.getTopicDirectionId());
			vo.setTopicId(e.getTopicId());
			vo.setTopicTargetId(e.getId());
			int count = planService.getMeNoCompleteNum(e.getId(), labMemberId);
			vo.setIsPlanNotFinish(count > 0 ? BoolEnum.TRUE.getValue() : BoolEnum.FALSE.getValue());
			return vo;
		}).collect(Collectors.toList());

		PlanTopicVo planTopicVo = new PlanTopicVo();
		planTopicVo.setState(topic.getState());
		planTopicVo.setTopicId(topic.getId());
		planTopicVo.setTopicName(topic.getName());
		planTopicVo.setTopicTargetList(pttlvs);
		return planTopicVo;
	}

	/** end */

	/**
	 * 成员筛选列表
	 *
	 * @param labId
	 * @param labMemberId
	 * @param isOwner
	 * @return
	 */
	public List<MemberInfoVo> getPlanMemberScreenList(Long labId, Long labMemberId, boolean isOwner) {
		List<MemberInfoVo> memberList = new ArrayList<>();
		if (isOwner) {
			memberList = labMemberService.selectMemberVoList(labId, LabMemberEnum.State.STATE_IN.getValue());
		} else {
			List<Long> labMemberIdList = new ArrayList<Long>();
			labMemberIdList.add(labMemberId);
			boolean isLeader = teamLogic.isLeaderOrPi(labId, labMemberId);
			if (isLeader) {
				TeamMember teamMember = teamMemberService.selectOneByLabIdAndLabMemberId(labId, labMemberId);
				List<TeamMember> teamList = teamMemberService.selectListByTeamIdAndState(teamMember.getTeamId(),
						TeamMemberStateEnum.IN.getState());
				List<Long> labMemberIds = teamList.stream().map(TeamMember::getLabMemberId)
						.collect(Collectors.toList());
				labMemberIdList.addAll(labMemberIds);
			}
			List<Long> labMemberIds = topicMemberService.getIdenticalTopicLabMemberIds(labMemberId);
			labMemberIdList.addAll(labMemberIds);

			labMemberIds = labMemberIds.stream().distinct().collect(Collectors.toList());
			memberList = labMemberService.selectMemberVoListByIds(labMemberIdList);
		}

		List<MemberInfoVo> memberVoList = new ArrayList<>();
		for (MemberInfoVo infoVo : memberList) {
			if (infoVo.getLabMemberId().equals(labMemberId)) {
				memberVoList.add(0, infoVo);
			} else {
				memberVoList.add(infoVo);
			}
		}
		return memberVoList;
	}

	public PlanVo planTargetAdd(UserInfoVo userInfo, PlanTargetAddVo addVo) {
		Optional<PlanAddVo> opt = addVo.getTopicExperimentList().stream().filter(e -> e.getIsStart() == 1).findFirst();
		Assert.isTrue(opt.isPresent(), "未设置开始实验");

		TopicTarget target = topicTargetService.selectById(addVo.getTopicTargetId());
		Assert.notNull(target, "实验流不存在");

		boolean isTopicMember = topicLogic.isTopicMember(target.getTopicId(), addVo.getLabMemberId());
		Assert.isTrue(isTopicMember, "计划人不是该课题成员");

		boolean isAddPlan = planService.isAddPlan(addVo.getTopicTargetId());
		Assert.isTrue(isAddPlan, "实验流已经在计划中不能重复添加");

		if(addVo.getPlanTime()==null) {
			Date planTime = planService.getPlanTime(userInfo.getLabMemberId(), new Date(), 1);
			addVo.setPlanTime(planTime);
		}
		
		PlanTargetGroup targetGroup = planTargetGroupService.getNewestPlanTargetGroup(addVo.getTopicTargetId());
		if (targetGroup != null) {
			planTargetGroupService.endTargetGroup(targetGroup.getId());
		}
		
		PlanVo vo = null;
		targetGroup = new PlanTargetGroup();
		targetGroup.setPlanTime(addVo.getPlanTime());
		targetGroup.setTopicId(target.getTopicId());
		targetGroup.setTopicDirectionId(target.getTopicDirectionId());
		targetGroup.setTopicTargetId(target.getId());
		targetGroup.setState(TopicStateEnum.UNDER_WAY.getValue());
		targetGroup = planTargetGroupService.insert(targetGroup);


		List<TopicExperiment> experimentList = topicExperimentService.getTopicExperimentList(addVo.getTopicTargetId());
		List<PlanAddVo> addVoList = addVo.getTopicExperimentList();
		for (TopicExperiment topicExperiment : experimentList) {
			
			Experiment experiment = experimentService.selectById(topicExperiment.getExperimentId());
			if (experiment.getState().equals(ExperimentStateEnum.COMPLETE.getValue())) {
				experiment = experimentService.experimentAdd(topicExperiment);
				topicExperiment.setExperimentId(experiment.getId());
			}
			
			PlanAddVo planAddVo = addVoList.stream().filter(m -> m.getTopicExperimentId().equals(topicExperiment.getId())).findFirst().orElse(null);
			if(planAddVo!=null) {
				PlanExperimentGroup experimentGroup = new PlanExperimentGroup();
				experimentGroup.setTargetGroupId(targetGroup.getId());
				experimentGroup.setTopicExperimentId(topicExperiment.getId());
				experimentGroup = planExperimentGroupService.insert(experimentGroup);

				if (BoolEnum.TRUE.getValue().equals(planAddVo.getIsStart()) && vo == null) {
					Plan plan = this.savePlan(topicExperiment, targetGroup.getId(), experimentGroup.getId(),
							addVo.getPlanTime(), addVo.getLabId(), addVo.getLabMemberId());
					vo = MyBeanUtils.copyBean(plan, PlanVo.class);
					vo.setMethodTypeName(topicExperiment.getMethodTypeName());
					vo.setColor(target.getColor());
					vo.setIsCheck(topicExperiment.getIsCheck());
					Topic topic = topicService.selectById(topicExperiment.getTopicId());
					vo.setTopicState(topic.getState());
				}
				this.memberDoExperimentTargetJoinPlan(userInfo, topicExperiment);
			}
		}
		
		return vo;
	}

	public List<TopicListVo> getTopicIndexList(UserInfoVo userInfo, Long labMemberId) {
		PlanMemberRoleVo roleVo = this.getMemberRole(userInfo, labMemberId);
		Assert.isTrue(!PlanMemberRoleEnum.ORDINARY.getValue().equals(roleVo.getRole()), "您没有权限操作他人计划!");
		List<TopicListVo> topicList = topicService.getIndexTopicList(userInfo.getLabId(), labMemberId);
		if (CollectionUtils.isNotEmpty(topicList)) {
			if (PlanMemberRoleEnum.MAIN_EXECUTORID.getValue().equals(roleVo.getRole())) {
				for (Iterator<TopicListVo> iterator = topicList.iterator(); iterator.hasNext();) {
					TopicListVo topicVo = iterator.next();
					if (!userInfo.getLabMemberId().equals(topicVo.getExecutorId())) {
						iterator.remove();
					}
				}
			}
		}
		return topicList;
	}

	public List<TopicExperimentVo> getExperimentList(UserInfoVo userInfo, Long topicTargetId, Long planId) {
		PlanTargetGroup group = null;
		Plan plan = null;
		if (planId != null) {
			plan = planService.selectById(planId);
			group = planTargetGroupService.getById(plan.getTargetGroupId());
		} else {
			group = planTargetGroupService.getNewestPlanTargetGroup(topicTargetId);
		}

		Map<Long, List<Plan>> planMap = new HashMap<Long, List<Plan>>();
		Map<Long, List<PlanExperimentGroup>> experimentGroupMap = new HashMap<Long, List<PlanExperimentGroup>>();
		if (group != null) {
			List<Plan> planList = planService.getNewPlanList(group.getId());
			planMap = planList.stream().collect(Collectors.groupingBy(Plan::getTopicExperimentId));
			List<PlanExperimentGroup> experimentGroupList = planExperimentGroupService
					.getExperimentGroupList(group.getId());
			experimentGroupMap = experimentGroupList.stream()
					.collect(Collectors.groupingBy(PlanExperimentGroup::getTopicExperimentId));
		}

		TopicTarget target = topicTargetService.selectById(topicTargetId);
		Topic topic = topicService.selectById(target.getTopicId());

		List<TopicExperimentVo> experimentVoList = topicExperimentService.getTopicExperimentVoList(topicTargetId);
		if (CollectionUtils.isNotEmpty(experimentVoList)) {
			for (TopicExperimentVo vo : experimentVoList) {
				vo.setColor(target.getColor());
				if (!TopicStateEnum.COMPLETE.getValue().equals(topic.getState()) && group != null
						&& TopicStateEnum.UNDER_WAY.getValue().equals(group.getState())) {
					PlanMemberRoleVo memberRole = this.getMemberRole(userInfo, vo.getExecutorId());
					if (memberRole.getRole() != PlanMemberRoleEnum.ORDINARY.getValue()) {
						if (memberRole.getRole() == PlanMemberRoleEnum.MAIN_EXECUTORID.getValue()) {
							if (topic.getExecutorId().equals(userInfo.getLabMemberId())) {
								vo.setIsOperatePlan(BoolEnum.TRUE.getValue());
							}
						} else {
							vo.setIsOperatePlan(BoolEnum.TRUE.getValue());
						}
					}
				}

				if (userInfo.getLabMemberId().equals(topic.getExecutorId())
						|| userInfo.getLabMemberId().equals(vo.getExecutorId())) {
					if (vo.getIsDelete().equals(IsDeleteEnum.NULLIFY.getValue())) {
						vo.setOperateType(3);
					} else if (BoolEnum.TRUE.getValue().equals(vo.getIsCheck())) {
						int count = 0;
						List<Experiment> list = experimentService.getExperimentList(vo.getTopicExperimentId(), null);
						if (CollectionUtils.isNotEmpty(list)) {
							List<Long> experimentIdS = list.stream().map(Experiment::getId)
									.collect(Collectors.toList());
							count = fileManageService.selectCount(Arrays.asList(OssFileEnum.AnalyzeDataFile.getKey(),
									OssFileEnum.PrimaryDataFile.getKey()), experimentIdS);
						}
						vo.setOperateType(count == 0 ? 1 : 2);
					}
				}

				if (group != null) {
					vo.setTargetGroupState(group.getState());
					vo.setTargetGroupId(group.getId());

					if (plan != null && plan.getTopicExperimentId().equals(vo.getTopicExperimentId())) {
						vo.setExperimentId(plan.getExperimentId());
						vo.setExperimentGroupId(plan.getExperimentGroupId());
						vo.setPlanId(plan.getId());
					} else {
						List<Plan> list = planMap.get(vo.getTopicExperimentId());
						List<PlanExperimentGroup> list2 = experimentGroupMap.get(vo.getTopicExperimentId());
						if (CollectionUtils.isNotEmpty(list)) {
							Plan plan2 = list.get(0);
							vo.setExperimentId(plan2.getExperimentId());
							vo.setExperimentGroupId(plan2.getExperimentGroupId());
							vo.setPlanId(plan2.getExperimentId());
						} else if (CollectionUtils.isNotEmpty(list2)) {
							vo.setExperimentGroupId(list2.get(0).getId());
						}
					}
				}

			}
		}

		return topicLogic.setExperimentVoList(userInfo.getLabMemberId(), experimentVoList,
				group != null ? group.getId() : null);
	}

	public PlanVo planExperimentAdd(UserInfoVo userInfo, PlanExperimentAddVo addVo) {
		if (addVo.getPlanTime() != null) {
			String newDateStr = DateUtil.dateString(new Date(), "yyyy-MM-dd HH");
			Date newDate = DateUtil.stringToDate(newDateStr, "yyyy-MM-dd HH");
			Assert.isTrue(addVo.getPlanTime().getTime() >= newDate.getTime(), "计划时间必须大于当前时间");
		}

		TopicExperiment topicExperiment = topicExperimentService.selectById(addVo.getTopicExperimentId());
		Assert.notNull(topicExperiment, "实验目标不存在");

		Experiment experiment = experimentService.selectById(topicExperiment.getExperimentId());
		Assert.notNull(experiment, "实验不存在");
		boolean isAdd = true;
		if (experiment.getState().equals(ExperimentStateEnum.COMPLETE.getValue())) {
			experiment = experimentLogic.repeatExperiment(topicExperiment);
			topicExperiment.setExperimentId(experiment.getId());
		} else {
			Plan plan = planService.getPlanByExperimentId(topicExperiment.getExperimentId());
			if (plan != null) {
				planService.deleteById(plan.getId(), plan.getLabId());
				isAdd = false;
			}
		}
		PlanExperimentGroup experimentGroup = planExperimentGroupService.getExperimentGroup(addVo.getTargetGroupId(),
				addVo.getTopicExperimentId());
		Assert.notNull(experimentGroup, "计划实验组不存在");

		Plan plan = this.savePlan(topicExperiment, addVo.getTargetGroupId(), experimentGroup.getId(),
				addVo.getPlanTime(), addVo.getLabId(), addVo.getLabMemberId());
		PlanVo vo = MyBeanUtils.copyBean(plan, PlanVo.class);
		vo.setMethodTypeName(topicExperiment.getMethodTypeName());
		TopicTarget target = topicTargetService.selectById(topicExperiment.getTopicTargetId());
		vo.setColor(target.getColor());
		vo.setIsCheck(topicExperiment.getIsCheck());
		Topic topic = topicService.selectById(topicExperiment.getTopicId());
		vo.setTopicState(topic.getState());
		if (isAdd) {
			this.managerAddPlan(userInfo, topicExperiment);
		} else {
			this.managerModifyPlan(userInfo, topicExperiment);
		}
		return vo;
	}

	private void managerAddPlan(UserInfoVo userInfo, TopicExperiment topicExperiment) {
		if (!userInfo.getLabMemberId().equals(topicExperiment.getExecutorId())) {
			Users user = usersService.selectUser(userInfo.getLabId(), topicExperiment.getExecutorId(),
					BoolEnum.TRUE.getValue());
			if (user != null) {
				ManagerAddPlanTemplate temp = new ManagerAddPlanTemplate(userInfo.getLabId(), user.getId(),
						topicExperiment.getExecutorId(), userInfo.getName(), topicExperiment.getMethodTypeName(),
						topicExperiment.getTopicId(), topicExperiment.getTopicTargetId());
				messageProducer.sendMessagePush(temp);
			}
		}
	}

	private void managerModifyPlan(UserInfoVo userInfo, TopicExperiment topicExperiment) {
		if (!userInfo.getLabMemberId().equals(topicExperiment.getExecutorId())) {
			Users user = usersService.selectUser(userInfo.getLabId(), topicExperiment.getExecutorId(),
					BoolEnum.TRUE.getValue());
			if (user != null) {
				ManagerModifyPlanTimeTemplate temp = new ManagerModifyPlanTimeTemplate(userInfo.getLabId(),
						user.getId(), topicExperiment.getExecutorId(), userInfo.getName(),
						topicExperiment.getMethodTypeName(), topicExperiment.getTopicId(),
						topicExperiment.getTopicTargetId());
				messageProducer.sendMessagePush(temp);
			}
		}
	}

	private void managerRemovePlan(UserInfoVo userInfo, TopicExperiment topicExperiment) {
		if (!userInfo.getLabMemberId().equals(topicExperiment.getExecutorId())) {
			Users user = usersService.selectUser(userInfo.getLabId(), topicExperiment.getExecutorId(),
					BoolEnum.TRUE.getValue());
			if (user != null) {
				ManagerRemovePlanTemplate temp = new ManagerRemovePlanTemplate(userInfo.getLabId(), user.getId(),
						topicExperiment.getExecutorId(), userInfo.getName(), topicExperiment.getMethodTypeName());
				messageProducer.sendMessagePush(temp);
			}
		}
	}

	private void memberDoExperimentTargetJoinPlan(UserInfoVo userInfo, TopicExperiment topicExperiment) {
		if (!userInfo.getLabMemberId().equals(topicExperiment.getExecutorId())) {
			Users user = usersService.selectUser(userInfo.getLabId(), topicExperiment.getExecutorId(),
					BoolEnum.TRUE.getValue());
			if (user != null) {
				MemberDoExperimentTargetJoinPlanTemp temp = new MemberDoExperimentTargetJoinPlanTemp(
						userInfo.getLabId(), user.getId(), topicExperiment.getExecutorId(), userInfo.getName(),
						topicExperiment.getMethodTypeName(), topicExperiment.getTopicId(),
						topicExperiment.getTopicTargetId());
				messageProducer.sendMessagePush(temp);
			}
		}
	}

	/**
	 * 保存计划
	 * 
	 * @param topicExperiment
	 * @param targetGroupId
	 * @param experimentGroupId
	 * @param planTime
	 * @param labId
	 * @param labMemberId
	 * @return
	 */
	public Plan savePlan(TopicExperiment topicExperiment, Long targetGroupId, Long experimentGroupId, Date planTime,
			Long labId, Long labMemberId) {

		Assert.notNull(topicExperiment, "实验不存在");
		Assert.isTrue(topicExperiment.getExecutorId().equals(labMemberId), "实验执行人与计划人不一致");

		Plan plan = new Plan();
		plan.setLabId(labId);
		plan.setTopicId(topicExperiment.getTopicId());
		plan.setTopicDirectionId(topicExperiment.getTopicDirectionId());
		plan.setTopicTargetId(topicExperiment.getTopicTargetId());
		plan.setTopicExperimentId(topicExperiment.getId());
		plan.setExperimentId(topicExperiment.getExperimentId());

		plan.setTargetGroupId(targetGroupId);
		plan.setExperimentGroupId(experimentGroupId);
		plan.setLabMemberId(labMemberId);

		planTime = planService.getPlanTime(labMemberId, planTime, 1);
		plan.setPlanTime(planTime);
		plan = planService.insert(plan);

		Experiment experiment = new Experiment();
		experiment.setId(topicExperiment.getExperimentId());
		experiment.setExecutorId(topicExperiment.getExecutorId());
		experiment.setStartTime(plan.getPlanTime());
		experimentService.updateById(experiment);

		topicService.setTopicStateUnderWay(topicExperiment.getTopicId());
		experimentLogic.experimentInfoSave(experiment.getId());
		return plan;
	}

	public void experimentDelete(UserInfoVo userInfo, Long experimentGroupId) {
		PlanExperimentGroup group = planExperimentGroupService.selectById(experimentGroupId);
		if (group != null) {
			planExperimentGroupService.deleteById(experimentGroupId);
			planService.deleteByExperimentGroupId(experimentGroupId);
			TopicExperiment topicExperiment = topicExperimentService.selectById(group.getTopicExperimentId());
			this.managerRemovePlan(userInfo, topicExperiment);
		}
	}

	public void experimentGroupAdd(Long targetGroupId, Long topicExperimentId) {
		PlanExperimentGroup experimentGroup = planExperimentGroupService.getExperimentGroup(targetGroupId,
				topicExperimentId);
		if (experimentGroup == null) {
			experimentGroup = new PlanExperimentGroup();
			experimentGroup.setTargetGroupId(targetGroupId);
			experimentGroup.setTopicExperimentId(topicExperimentId);
			planExperimentGroupService.insert(experimentGroup);
		} else if (experimentGroup.getIsDelete().equals(BoolEnum.TRUE.getValue())) {
			experimentGroup.setIsDelete(BoolEnum.FALSE.getValue()); 
			planExperimentGroupService.updateById(experimentGroup);
		}
	}

	public ExperimentStartVo experimentStart(Long topicExperimentId, UserInfoVo userInfo) {
		Long experimentId = null;

		TopicExperiment topicExperiment = topicExperimentService.selectById(topicExperimentId);
		Assert.notNull(topicExperiment, "实验不存在");
		Assert.isTrue(topicExperiment.getExecutorId().equals(userInfo.getLabMemberId()), "你没有权限操作该实验");
		PlanTargetGroup targetGroup = planTargetGroupService
				.getNewestPlanTargetGroup(topicExperiment.getTopicTargetId());
		Assert.notNull(targetGroup, "该实验未加入计划组中");
		PlanExperimentGroup experimentGroup = planExperimentGroupService.getExperimentGroup(targetGroup.getId(),
				topicExperimentId);
		Assert.notNull(experimentGroup, "该实验未加入计划组中");

		Experiment experiment = experimentService.selectById(topicExperiment.getExperimentId());
		if (experiment.getState().equals(ExperimentStateEnum.COMPLETE.getValue())) {
			experiment = experimentLogic.repeatExperiment(topicExperiment);

			topicExperiment.setExperimentId(experiment.getId());
			this.savePlan(topicExperiment, targetGroup.getId(), experimentGroup.getId(), new Date(),
					userInfo.getLabId(), userInfo.getLabMemberId());
			experimentId = experiment.getId();
		} else {
			Plan plan = planService.getPlanByExperimentId(topicExperiment.getExperimentId());
			if (plan == null) {
				this.savePlan(topicExperiment, targetGroup.getId(), experimentGroup.getId(), new Date(),
						userInfo.getLabId(), userInfo.getLabMemberId());
			}
			experimentId = topicExperiment.getExperimentId();
			experimentLogic.experimentInfoSave(experiment.getId());
		}

		experiment = experimentService.selectById(experimentId);
		ExperimentStartVo startVo = new ExperimentStartVo();
		startVo.setExperimentId(experimentId);
		startVo.setIsMethodStart(experiment.getMethodId() == null && experiment.getIsImport() == 0 ? 0 : 1);
		return startVo;
	}

	public PlanMemberRoleVo getMemberRole(UserInfoVo userInfo, Long labMemberId) {
		PlanMemberRoleVo vo = new PlanMemberRoleVo();
		vo.setLoginerId(userInfo.getLabMemberId());
		vo.setLabMemberId(labMemberId);
		if (userInfo.getLabMemberId().equals(labMemberId)) {
			vo.setRole(PlanMemberRoleEnum.OWN.getValue());
			return vo;
		}
		if (userInfo.getIsOwner()) {
			vo.setRole(PlanMemberRoleEnum.PI.getValue());
			return vo;
		}
		TeamMemberVo teamLeader = teamLogic.getLeaderOfTeamMember(userInfo.getLabId(), labMemberId);
		if (teamLeader != null && teamLeader.getLabMemberId().equals(userInfo.getLabMemberId())) {
			vo.setRole(PlanMemberRoleEnum.LEADER.getValue());
			return vo;
		}
		boolean isMainExecutor = topicMemberService.isMainExecutor(userInfo.getLabMemberId(), labMemberId);
		if (isMainExecutor) {
			vo.setRole(PlanMemberRoleEnum.MAIN_EXECUTORID.getValue());
		}
		return vo;
	}

	public void deletePlan(Long planId, UserInfoVo userInfo) {
		Plan plan = planService.selectById(planId);
		if (plan != null) {
			planService.deleteById(planId, userInfo.getLabId());
			TopicExperiment topicExperiment = topicExperimentService.selectById(plan.getTopicExperimentId());
			this.managerRemovePlan(userInfo, topicExperiment);
		}
	}

}
